﻿using System;
using System.Collections.Generic;
using System.Linq;
using Metro.Kashikoi.Common.ExceptionHandling;
using Metro.Kashikoi.Service.Common.Entity;
using Metro.Kashikoi.ServiceContract.Security;
using Metro.Kashikoi.Service.Security.Entity;
using Metro.Kashikoi.Common;
using Metro.Kashikoi.ServiceContract.Location;

namespace Metro.Kashikoi.Service.Security.Business
{
    class SecurityFacade : ISecurityFacade
    {
        /// <summary>
        /// Ceaetes the user.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="user">The user.</param>
        public void CeaeteUser(IUnitOfWork context, User user)
        {
            var rep = new Repository<User>(context);
            rep.Add(user);
        }

        /// <summary>
        /// Updates the user.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="user">The user.</param>
        public void UpdateUser(IUnitOfWork context, User user)
        {
            var rep = new Repository<UserBase>(context);
            var entity = rep.GetUser(user.Id, user.Login);
            entity.Login = user.Login;
            entity.FirstName = user.FirstName;
            entity.LastName = user.LastName;
            entity.Password = user.Password;
            entity.CellPhone = user.CellPhone;
            entity.GroupIdCol = user.GroupIdCol;
            entity.EmailAddress = user.EmailAddress;
        }

        /// <summary>
        /// Deletes the user.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="Id">The id.</param>
        public void DeleteUser(IUnitOfWork context, int Id)
        {
            var rep = new Repository<UserBase>(context);
            var entity = rep.GetUser(Id, null);
            context.Remove(entity);
        }

        /// <summary>
        /// Gets all users.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        public IList<User> GetAllUsers(IUnitOfWork context)
        {
            var rep = new Repository<UserBase>(context);
            return rep.GetQuery().OfType<User>().ToList();
        }

        /// <summary>
        /// Gets the user by id.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        public User GetUserById(IUnitOfWork context, int id)
        {
            var rep = new Repository<UserBase>(context);
            return rep.Where<User>(o => o.Id == id).Single();
        }

        /// <summary>
        /// Mantains the GRP id.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="user">The user.</param>
        public void MantainGrpId(IUnitOfWork context, ServiceContract.Security.User user)
        {
            //var rep = new Repository<User>(context);
            //var entity = rep.GetUser(user.Id);
        }

        public bool ValidateUser(IUnitOfWork context, string id, string password)
        {
            bool result = false;
            var rep = new Repository<UserBase>(context);
            var entity = rep.GetLoginUser(id, password);

            if (entity != null)
            {
                result = true;
                if (!UserTokens.tokenDic.ContainsKey(id))
                {
                    UserTokens.tokenDic.Add(id, UserTokens.RandomString());
                }
            }
            return result;
        }

        public void CeaeteUserGroup(IUnitOfWork context, UserGroup userGroup)
        {
            var rep = new Repository<UserGroup>(context);
            rep.Add(userGroup);
        }

        public void UpdateUserGroup(IUnitOfWork context, ServiceContract.Security.UserGroup userGroup)
        {
            var rep = new Repository<UserGroup>(context);
            var entity = rep.GetUserGroup(userGroup.Id);
            entity.GroupName = userGroup.GroupName;
            entity.Permisions = userGroup.Permisions;
            entity.Users = userGroup.Users;
        }

        public void DeleteUserGroup(IUnitOfWork context, int Id)
        {
            var rep = new Repository<UserGroup>(context);
            var entity = rep.GetUserGroup(Id);
            rep.Remove(entity);
        }

        public IList<UserGroup> GetAllUserGroups(IUnitOfWork context)
        {
            var rep = new Repository<UserGroup>(context);
            return rep.GetQuery().ToList<UserGroup>();
        }

        public void AddUser(IUnitOfWork context, User user, UserGroup userGroup)
        {
            var rep = new Repository<UserBase>(context);
            var entity = rep.GetUser(user.Id, null);

            if (!entity.GroupIdCol.Contains(userGroup.Id))
            {
                entity.GroupIdCol.Add(userGroup.Id);
            }            
        }

        public void RemoveUser(IUnitOfWork context, User user, UserGroup userGroup)
        {
            var rep = new Repository<UserBase>(context);
            var entity = rep.GetUser(user.Id, null);

            if (entity.GroupIdCol.Contains(userGroup.Id))
            {
                entity.GroupIdCol.Remove(userGroup.Id);
            }
        }

        public UserGroup GetUserGroupById(IUnitOfWork context, int id)
        {
            var rep = new Repository<UserGroup>(context);
            var entity = rep.GetUserGroup(id);
            return (UserGroup)entity;
        }


        public User GetUserByLogin(IUnitOfWork context, string login)
        {
            var rep = new Repository<UserBase>(context);
            var entity = rep.GetUser(0, login);
            return (User)entity;
        }


        public IList<User> GetUserList(IUnitOfWork context, int userGroupId)
        {
            var rep = new Repository<UserBase>(context);
            var entity = rep.GetUsers(userGroupId);
            return (IList<User>)entity;
        }


        public void AddRoute(IUnitOfWork context, UserGroup userGroup, Region region)
        {
            var rep = new Repository<UserGroup>(context);
            var entity = rep.GetUserGroup(userGroup.Id);

            if (region.Children.Count > 0)
            {
                RouteRecursive(userGroup, region, "A");
            }

        }

        public void RemoveRoute(IUnitOfWork context, UserGroup userGroup, Region region)
        {
            var rep = new Repository<UserGroup>(context);
            var entity = rep.GetUserGroup(userGroup.Id);

            if (region.Children.Count > 0)
            {
                RouteRecursive(userGroup, region, "R");
            }
        }

        protected static void RouteRecursive(UserGroup userGroup, Region region, string opertion)
        {
            if (region == null)
            {
                return;
            }

            if (opertion == "A")
            {
                userGroup.Routes.Add(region);
            }
            else if (opertion == "R")
            {
                userGroup.Routes.Remove(region);
            }
            else
            {
                return;
            }

            foreach (var item in region.Children)
            {
                RouteRecursive(userGroup, item, opertion);
            }
        }



      
    }
}
